package cl.lexer;

import java.util.ArrayList;
import java.util.List;

import cl.lexer.validator.TokenValidator;
import cl.lexer.validator.Validators;

public class Lexer {
    
    public List<Token> parse(StringBuilder contents) throws LexerException {
        if(contents.length() == 0) {
            throw new LexerException("Trying to parse an empty string");
        }
        
        
        List<Token> tokens = new ArrayList<Token>();
        char[] chars = contents.toString().toCharArray();
        
        String current = "";
        List<TokenValidator> allowed = Validators.getAll();
        TokenValidator last = null;
        
        for(char c : chars) {            
            for(int i = 0; i < allowed.size(); i++) {
                if(!allowed.get(i).possiblyValid(current + c)) {
                    if(allowed.get(i).isValid(current)) {
                        last = allowed.get(i);
                    }
                    allowed.remove(i--);
                }
            }
            
            if(allowed.isEmpty()) {
                addToken(tokens, last, current);
                
                current = "" + c;
                allowed = Validators.getAll();
                last = null;
            } else {
                current += c;
            }
        }
        
        for(TokenValidator def : allowed) {
            if(def.isValid(current)) {
                last = def;
            }
        }
        
        addToken(tokens, last, current);
        
        return tokens;
    }
    
    private void addToken(List<Token> tokens, TokenValidator def, String current) throws LexerException {
        if(def == null || !def.isValid(current)) {
            throw new LexerException("Unknown token: " + current);
        }
        
        if(def.getType() != TokenType.WHITESPACE) {
            tokens.add(def.generateToken(current));
        }
    }
}
